package cn.b.sky.mes.pp.service.impl;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import cn.b.sky.mes.pp.dao.ProductOrderDao;
import cn.b.sky.mes.pp.dao.ProductionOrderDao;
import cn.b.sky.mes.pp.enums.OrderStatusCode;
import cn.b.sky.mes.pp.enums.PorderStatusCode;
import cn.b.sky.mes.pp.model.ProductOrder;
import cn.b.sky.mes.pp.model.ProductionOrder;
import cn.b.sky.mes.pp.model.condition.ProductionOrderCondition;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.b.sky.mes.cm.model.BOMComponent;
import cn.b.sky.mes.cm.model.Material;
import cn.b.sky.mes.cm.service.BOMService;
import cn.b.sky.mes.cm.service.MaterialService;
import cn.b.sky.common.constants.SystemConstant;
import cn.b.sky.common.exception.ImeException;
import cn.b.sky.common.model.Page;
import cn.b.sky.common.utils.DateUtils;
import cn.b.sky.user.SecurityContextUtil;
import cn.b.sky.mes.cm.enums.NumberRuleEnums;
import cn.b.sky.user.service.NumberRuleService;
import cn.b.sky.mes.pp.service.ProductOrderService;
import cn.b.sky.mes.pp.service.ProductionControlService;

@Service("productOrderService")
public class ProductOrderServiceImpl implements ProductOrderService {
  
  private static final Logger LOGGER = LoggerFactory.getLogger(ProductOrderServiceImpl.class);
  @Autowired
  private ProductOrderDao productOrderDao;

  @Autowired
  private ProductionOrderDao productionOrderDao;

  @Resource
  private ProductionControlService productionControlService;

  @Resource
  private MaterialService materialService;

  @Resource
  private BOMService bomService;

  @Resource
  private NumberRuleService numberRuleService;

  @Override
  public Page getProductOrdersByCondition(ProductionOrderCondition condition) {
    if (condition == null) {
      condition = new ProductionOrderCondition();
    }
    //默认按照创建时间排序
    if (StringUtils.isBlank(condition.getOrderField())) {
      condition.setOrderField("CreateDateTime");
    }
    List<ProductOrder> order = productOrderDao.selectProductOrdersByCondition(condition);
    int count = productOrderDao.selectProductOrderCount(condition);
    condition.setData(order);
    condition.setTotalCount(count);
    return condition;
  }

  @Override
  public ProductOrder getProductOrderByPk(String siteCode, String productOrderNum) {
    if (StringUtils.isBlank(siteCode) || StringUtils.isBlank(productOrderNum)) {
      return null;
    }

    return this.productOrderDao.selectProductOrdersByPk(siteCode, productOrderNum);
  }

  @Override
  public List<ProductionOrder> selectProductionOrdersByProductOrder(String siteCode, String productOrderNum) {
    if (!StringUtils.isBlank(siteCode) && !StringUtils.isBlank(productOrderNum)) {
      return productionOrderDao.selectProductOrdersByProductOrderNum(siteCode, productOrderNum);
    }
    return null;
  }

  @Override
  public void saveProductOrder(ProductOrder order) {
    if (order != null && !StringUtils.isBlank(order.getProductOrderNum())) {
      productOrderDao.insertProductOrder(order);
    }

  }

  @Override
  public void modifyProductOrder(ProductOrder order) {
    if (order != null && !StringUtils.isBlank(order.getProductOrderNum())) {
      productOrderDao.updateProductOrder(order);
    }

  }

  @Override
  public void modifyNoCreateProductionOrder(ProductOrder order) {
    order.setModifyDate(new Date());
    order.setModifyUser(SecurityContextUtil.getCurrentUserName());
    if (order != null && !StringUtils.isBlank(order.getProductOrderNum())) {
      productOrderDao.updateNoCreateProductOrder(order);
    }
  }

  @Override
  public void deleteProductOrderByPk(String siteCode, String productOrderNum) {
    if (!StringUtils.isBlank(siteCode) && !StringUtils.isBlank(productOrderNum)) {
      productOrderDao.deleteProductOrderByPK(siteCode, productOrderNum);
    }
  }

  @Override
  public void closeSplitProductOrder(String productOrderNum, String siteCode) {
    if (!StringUtils.isBlank(siteCode) && !StringUtils.isBlank(productOrderNum)) {
      //判断是否有生产订单
      List<ProductionOrder> orders = productionOrderDao.selectUnClosedProductionOrdersByProductOrderNum(
          siteCode, productOrderNum, OrderStatusCode.CLOSE.getValue());
      if (orders != null && orders.size() > 0) {
        //关闭生产管理号
        productionControlService.closeProductionControl(siteCode, productOrderNum, "productOrder");
        //关闭生产订单
        ProductOrder productOrder = new ProductOrder();
        productOrder.setSiteCode(siteCode);
        productOrder.setProductOrderNum(productOrderNum);
        productOrder.setStatuseCode(OrderStatusCode.CLOSE.getValue());
        //临时借用字段，过滤完成的订单状态
        productOrder.setCustomer(OrderStatusCode.COMPLETE.getValue());
        productionOrderDao.closeProductionOrderByProductOrder(productOrder);
      }
      //关闭产品订单
      this.closeProductOrder(siteCode, productOrderNum, PorderStatusCode.CLOSE.getValue());
    }

  }

  @Override
  public void closeProductOrder(String siteCode, String productOrderNum, String value) {
    ProductOrder newOrder = new ProductOrder();
    newOrder.setSiteCode(siteCode);
    newOrder.setProductOrderNum(productOrderNum);
    newOrder.setStatuseCode(PorderStatusCode.CLOSE.getValue());
    newOrder.setModifyDateTime(new Date());
    newOrder.setModifyUser(SecurityContextUtil.getCurrentUserName());
    productOrderDao.updateNoCreateProductOrder(newOrder);
  }

  @Override
  public List<ProductionOrder> splitProductOrder(String materialCode, String siteCode, ProductOrder order) {
    Material material = materialService.selectMaterial(siteCode, materialCode);
    List<ProductionOrder> orders = new ArrayList<ProductionOrder>();
    if (material != null && material.getMakeFlag() == 1) {
      //自制件加入
      ProductionOrder productionOrder = new ProductionOrder();
      productionOrder.setMaterialCode(material.getMaterialCode());
      productionOrder.setMaterialText(material.getMaterialText());
      //默认第一级物料的计划数量为1
      productionOrder.setPlannedQuantity(1d);
      productionOrder.setPlannedstartDateTime(order.getPlannedstartDateTime());
      productionOrder.setPlannedendDateTime(order.getPlannedendDateTime());
      //计划时间
      if(order.getPlannedstartDateTime().before(new Date())){
        productionOrder.setOverToday(false);
      }
      //获取工艺
      productionOrder.setProcesses(materialService.selectLastProcessByMaterial(siteCode, materialCode));

      orders.add(productionOrder);
      if (!StringUtils.isBlank(material.getBomCode())) {
        //递归分解自制件的物料 这里的数量用未分解的数量来算，订单可以多次分解
        orders.addAll(setIsMakeMaterialToOrders(material, siteCode, 1, 1d, order.getPlannedstartDateTime(),
            order.getPlannedendDateTime()));
      }
    }
    return orders;
  }

  /**
   * 
   * <strong>Title : setIsMakeMaterialToOrders<br></strong>
   * <strong>Description : </strong>递归分解产品订单，自制件<br> 
   * <strong>Create on : 2016-1-20 下午1:24:17<br></strong>
   * <p>
   * @param material
   * @param siteCode
   * @param count
   * @param pquantity 父bom的数量，子bom计划数量是，父bom*pquantity
   * @param beginDate 物料的提前期计算，开始时间
   * @param endDate 物料的提前期计算，结束时间
   * void
   * @throws 
   * @author lidapeng<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  private List<ProductionOrder> setIsMakeMaterialToOrders(Material material, String siteCode, int count,
      Double pquantity, Date beginDate, Date endDate) {
    //预防出现重复嵌套，程序出现死循环
    if (count > 1000) {
      throw ImeException.newException("productOrderhasSameBom.M");
    }
    List<ProductionOrder> orders = new ArrayList<ProductionOrder>();
    String bomCode = material.getBomCode();
    if (!StringUtils.isBlank(bomCode)) {
      count++;
      List<BOMComponent> components = bomService.getBOMComponentByBom(siteCode, bomCode);
      for (BOMComponent component : components) {
        if (components != null && !StringUtils.isBlank(component.getComponentCode()) && component.getQuantity() > 0) {
          Material childMaterial = materialService.selectMaterial(siteCode, component.getComponentCode());
          if (childMaterial.getMakeFlag() == 1) {
            ProductionOrder productionOrder = new ProductionOrder();
            productionOrder.setMaterialCode(component.getComponentCode());
            productionOrder.setMaterialText(component.getComponentText());
            //默认组件的数量 计划数量
            Double plannedQuantity = component.getQuantity() == null ? 0 : component.getQuantity()* pquantity;
            productionOrder.setPlannedQuantity(plannedQuantity);
            productionOrder.setParentOrderNum(material.getMaterialCode());
            //获取工艺
            productionOrder.setProcesses(materialService.selectLastProcessByMaterial(siteCode,
                component.getComponentCode()));
            if(childMaterial.getMaterialLeadTimeNum() != null){
              productionOrder.setPlannedstartDateTime(getLeadDate(beginDate, -childMaterial.getMaterialLeadTimeNum().intValue()));
              productionOrder.setPlannedendDateTime(getLeadDate(endDate, -childMaterial.getMaterialLeadTimeNum().intValue()));
            }else{
              productionOrder.setPlannedstartDateTime(beginDate);
              productionOrder.setPlannedendDateTime(endDate);
            }
            if(productionOrder.getPlannedstartDateTime().before(new Date())){
              productionOrder.setOverToday(false);
            }
            orders.add(productionOrder);
            if (!StringUtils.isBlank(childMaterial.getBomCode())) {
              orders.addAll(setIsMakeMaterialToOrders(childMaterial, siteCode, count, plannedQuantity,
                  productionOrder.getPlannedstartDateTime(), productionOrder.getPlannedendDateTime()));
            }
          }
        }
      }
    }
    return orders;
  }
  
  private Date getLeadDate(Date date, int days) {
    Date result = DateUtils.getDateUtils().operationDay(date, days);
    try {
      Date minDate = DateUtils.getDateUtils(DateUtils.YYYY_MM_DD).parse("1970-01-01");
      return result.before(minDate) ? minDate : result;
    } catch (ParseException e) {
      LOGGER.error("转换日期失败DateUtils.getDateUtils().parse('1970-01-01')1", e);
      return result;
    }
  }

  @Override
  public void decompProductionOrders(ProductOrder order, List<ProductionOrder> productionOrders) {

    if (order != null && !StringUtils.isBlank(order.getProductOrderNum())) {
      //已分解数量要从新查询，防止并发操作，数据及时性,已现查的分解数量为准
      ProductOrder oldOrder = this.getProductOrderByPk(order.getSiteCode(), order.getProductOrderNum());
      if ((order.getDecompositionQuantity() + oldOrder.getDecomposedQuantity()) > oldOrder.getPlannedQuantity()) {
        throw ImeException.newException("decompositionQuantityGTquantity.M",
            new String[] { oldOrder.getPlannedQuantity() + "" });
      }

      Double decompositionQuantity = order.getDecompositionQuantity();
      Map<String, String> map = new HashMap<String, String>();
      String topOrderNum = null;
      for (ProductionOrder productionOrder : productionOrders) {
        String productionOrderNum = numberRuleService.selectNextNumber(order.getSiteCode(),
            NumberRuleEnums.PRODUCTIONORDERENCODINGRULE.getValue());
        String processStr = productionOrder.getProcessCode();
        if (!StringUtils.isBlank(processStr) && processStr.indexOf(SystemConstant.MIDDLE_SPLIT) != -1) {
          String[] str = processStr.split(SystemConstant.MIDDLE_SPLIT);
          productionOrder.setProcessCode(str[0]);
          productionOrder.setProcessRev(str[1]);
        } else {
          //工艺错误
          throw ImeException.newException("process.C,error.C");
        }
        productionOrder.setProductionOrderNum(productionOrderNum);
        //设置计划数量为，bom的数量*产品订单的分解数量
        productionOrder.setPlannedQuantity(decompositionQuantity * productionOrder.getPlannedQuantity());
        productionOrder.setProductOrderNum(order.getProductOrderNum());
        productionOrder.setSiteCode(order.getSiteCode());
        productionOrder.setStatuseCode(OrderStatusCode.CREATE.getValue());
        //order没有的信息
        productionOrder.setCustomer(oldOrder.getCustomer());
        productionOrder.setCustomerOrder(oldOrder.getCustomerOrder());
        productionOrder.setPriority(oldOrder.getPriority());
        productionOrder.setCreateDateTime(order.getCreateDateTime());
        productionOrder.setCreateUser(order.getCreateUser());
        productionOrder.setModifyDateTime(order.getModifyDateTime());
        productionOrder.setModifyUser(order.getModifyUser());
        if (!StringUtils.isBlank(productionOrder.getParentOrderNum())) {
          //list本来就是有顺序的，所以这里的map就是获取父节点的生产订单
          productionOrder.setParentOrderNum(map.get(productionOrder.getParentOrderNum()));
          productionOrder.setTopOrderNum(topOrderNum);
        } else {
          //父节点为空的就是topOrderNum
          topOrderNum = productionOrderNum;
          productionOrder.setParentOrderNum(null);
        }
        productionOrderDao.insertProductionOrder(productionOrder);
        map.put(productionOrder.getMaterialCode(), productionOrderNum);
      }
      order.setDecomposedQuantity(decompositionQuantity + oldOrder.getDecomposedQuantity());
      //分解数量等于计划数量则改变状态,这里float 类型不能直接判断相等
      order.setStatuseCode(PorderStatusCode.SPLIT_ORDER.getValue());//分解状态
      /* if ((order.getDecomposedQuantity() - order.getPlannedQuantity()) == 0) {
         order.setStatuseCode(PorderStatusCode.SPLIT_ORDER.getValue());
       }*/
      this.modifyNoCreateProductionOrder(order);
    }

  }
}
